package ru.averta.notes.other;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Service;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import ru.averta.notes.domain.ajax.AjaxCommonAnswer;

import java.util.*;

/**
 *
 * @author fedor.belov
 */

@Service
public class UtilsAjax {

    @Autowired private MessageSource messageSource;
    private static final Logger logger = LoggerFactory.getLogger(UtilsAjax.class);

    public static Object castAjax(Object source, Class targetClass) {
        if (source instanceof Collection) {
            return castCollectionAjax(source, targetClass);
        } else {
            return castSimpleAjax(source, targetClass);
        }
    }

    private static Object castSimpleAjax(Object source, Class targetClass) {
        if (source.getClass() == targetClass) {
            return source;
        }
        
        Object target = UtilsCommon.initObject(targetClass);
        BeanUtils.copyProperties(source, target);
        return target;
    }

    private static Object castCollectionAjax(Object source, Class targetClass) {
        try {
            Collection sourceCollection = (Collection) source;
            Collection targetCollection = (Collection) source.getClass().newInstance();

            for (Object sourceElement : sourceCollection) {
                targetCollection.add(castSimpleAjax(sourceElement, targetClass));
            }

            return targetCollection;
        } catch (Exception e) {
            throw new IllegalArgumentException(e);
        }
    }

    public List<String> castErrors(List<ObjectError> errors) {
        List<String> answer = null;
        if (errors != null  && !errors.isEmpty()) answer = new LinkedList<String>();

        for (ObjectError error : errors) {
            answer.add(errorToString(error.getCode()));
        }

        return answer;
    }

    public Map<String, String> castFieldErrors(List<FieldError> errors) {
        Map<String, String> answer = null;
        if (errors != null  && !errors.isEmpty()) answer = new HashMap<String, String>();

        for (FieldError error : errors) {
            answer.put(error.getField(), errorToString(error.getCode()));
        }

        return answer;
    }

    private String errorToString(String code) {
        try {
            return messageSource.getMessage(code, null, Locale.ENGLISH);
        } catch (Exception e) {
            logger.error("Не удалось определить перевод для ошибки " + code + ": " + e);
            return "[translation not found for " + code + "]";
        }
    }

    public static AjaxCommonAnswer getAjaxCommonOkAnswer(String display) {
        logger.trace("Возврашаем клиенту положительный ответ - {}", display);

        AjaxCommonAnswer answer = new AjaxCommonAnswer();
        answer.setDisplay(display);

        return answer;
    }

    public static AjaxCommonAnswer getAjaxErrorAnswer(String error) {
        logger.debug("Возврашаем клиенту ответ с ошибкой - {}", error);

        AjaxCommonAnswer answer = new AjaxCommonAnswer();
        answer.setHasErrors(true);
        answer.setDisplay(error);
        return answer;
    }

    public static AjaxCommonAnswer getAjaxErrorAnswer(Exception e) {
          return getAjaxErrorAnswer(e.toString());
    }
}
